// Jocara game project

#include "main_menu.h"

static std::list<MenuButton*> buttons;
static std::stack<Pages> page_history;
static SDL_Surface* bg;

GameModes MainMenu() {
  page_history.empty();
  SDL_Event event;
  SDL_Surface* screen = SDL_GetVideoSurface();
  bg = DrawBackground();
  SDL_BlitSurface(bg, NULL, screen, NULL);
  GameModes action = kQuit;
  bool run = true;
  LoadPage(kPageStart);
  while(run) {
    const Uint32 frame_started = SDL_GetTicks();
    // Event loop
    while(SDL_PollEvent(&event)) {
      switch(event.type) {
      case SDL_KEYDOWN:
        switch( event.key.keysym.sym ) {
        case SDLK_ESCAPE:
          Back();
          break;
        default:
          break;
        }
        break;
      case SDL_QUIT:
        action =  kQuit;
        run = false;
        break;
      case SDL_MOUSEBUTTONUP:
        if(event.button.button == SDL_BUTTON_LEFT) {
          std::list<MenuButton*>::iterator it;
          for(it = buttons.begin(); it != buttons.end(); ++it) {
            if((*it)->state()) {
              switch((*it)->id()) {
              case kNewGame:
                action =  kGame;
                run = false;
                break;
              case kLoadGame:
                LoadPage(kPageNotImplemented);
                break;
              case kOptions:
                LoadPage(kPageNotImplemented);
                break;
              case kExit:
                action =  kQuit;
                run = false;
                break;
              case kBack:
                Back();
                break;
              default:
                break;
              }
              break;
            }
          }
        }
        break;
      default:
        break;
      }
    }
    // Redraw buttons if needed
    std::list<MenuButton*>::iterator it;
    for(it = buttons.begin(); it != buttons.end(); ++it) {
      if((*it)->must_redraw()) {
        SDL_BlitSurface(bg, (*it)->rect(), screen, (*it)->rect());
        SDL_BlitSurface((*it)->image(), NULL, screen, (*it)->rect());
      }
    }
    SDL_Flip(screen);
    Wait(frame_started);
  }
  // Cleaning up
  SDL_FreeSurface(bg);
  return action;
}

SDL_Surface* DrawBackground() {
  SDL_Surface* screen = SDL_GetVideoSurface();
  SDL_Surface* bg = SDL_CreateRGBSurface(SDL_HWSURFACE, screen->w, screen->h,
                                         32, 0, 0, 0, 0);
  SDL_Surface* darkening_scaled = ScaleImage(kData[1], screen->w, screen->h);

  // Fill the background
  SDL_Rect rect = {0, 0, 92, 92};
  for(int y = 0; y < screen->h; y += 92) {
    for(int x = 0; x < screen->w; x += 92) {
      SDL_Rect pos = {x, y};
      SDL_BlitSurface(kData[0], &rect, bg, &pos);
    }
  }

  SDL_BlitSurface(darkening_scaled, NULL, bg, NULL);
  SDL_FreeSurface(darkening_scaled);
  return bg;
}

MenuButton::MenuButton(const Buttons id, const std::string text,
                       const int x_rel, const int y_rel):
  x_rel_(x_rel), y_rel_(y_rel), id_(id) {
  state_ = false;
  drawn_state_ = false;
  new_here_ = true;
  rect_ = NULL;
  SDL_Color color = {255, 255, 255};
  SDL_Surface* text_ = TTF_RenderText_Blended(kFontNormal, text.c_str(), color);
  SDL_Rect text_pos = {165 - text_->w / 2, 37 - text_->h / 2};
  for(unsigned int i = 0; i <= 1; ++i) {
    SDL_Surface* surf = SDL_CreateRGBSurface(SDL_HWSURFACE,
                        w_, h_, 32, 0, 0, 0, 0);
    imageset_[i] = SDL_DisplayFormatAlpha(surf);
    SDL_FreeSurface(surf);
    SDL_FillRect(imageset_[i], NULL, 0);
    SDL_Rect rect_ = {93 + 365 * i, 0, 365, 76};
    //SDL_BlitSurface(kData[0], &rect_, imageset_[i], NULL);
    AlphaBlit(kData[0], &rect_, imageset_[i], NULL);
    //SDL_gfxBlitRGBA(text_, NULL, imageset_[i], &text_pos);
    AlphaBlit(text_, NULL, imageset_[i], &text_pos);
  }
  SDL_FreeSurface(text_);
}

MenuButton::~MenuButton() {
  delete rect_;
  SDL_FreeSurface(imageset_[0]);
  SDL_FreeSurface(imageset_[1]);
}

inline SDL_Surface* MenuButton::image() {
  if(state_) return imageset_[0];
  else return imageset_[1];
}

SDL_Rect* MenuButton::rect() {
  if(rect_ == NULL) {
    SDL_Surface* screen = SDL_GetVideoSurface();
    rect_ =  new SDL_Rect();
    rect_->w = w_;
    rect_->h = h_;
    rect_->x = screen->w / 2 - w_ / 2 + x_rel_;
    rect_->y = screen->h / 2 - h_ / 2 + y_rel_;
  }
  return rect_;
}

void LoadPage(const Pages page) {
  SDL_Surface* screen = SDL_GetVideoSurface();
  SDL_BlitSurface(bg, NULL, screen, NULL);
  while(!buttons.empty()) {
    delete buttons.front();
    buttons.pop_front();
  }
  page_history.push(page);
  switch(page) {
  case kPageStart:
    buttons.push_back(new MenuButton(kNewGame, "New Game", 0, -113));
    buttons.push_back(new MenuButton(kLoadGame, "Load Game", 0, -38));
    buttons.push_back(new MenuButton(kOptions, "Options", 0, 37));
    buttons.push_back(new MenuButton(kExit, "Exit", 0, 112));
    break;
  case kPageNotImplemented: {
    SDL_Color color = {255, 255, 255};
    SDL_Surface* text = TTF_RenderText_Blended(kFontNormal,
                        "I'm sorry, Dave. I'm afraid I can't do that.", color);
    SDL_Rect pos =  {screen->w / 2 - text->w / 2,
                     screen->h / 2 - text->h / 2 - 50
                    };
    SDL_BlitSurface(text, NULL, screen, &pos);
    SDL_FreeSurface(text);
  }
  buttons.push_back(new MenuButton(kBack, "Okay", 0, 50));
  break;
  default:
    break;
  }
}

bool MenuButton::must_redraw() {
  int mouse_x, mouse_y;
  SDL_GetMouseState(&mouse_x, &mouse_y);
  state_ = PointInRect(mouse_x, mouse_y, rect());
  if(new_here_) {
    new_here_ = false;
    drawn_state_ = state_;
    return true;
  }
  if(state_ != drawn_state_) {
    drawn_state_ = state_;
    return true;
  } else return false;
}

void Back() {
  if(page_history.size() > 1) {
    page_history.pop();
    LoadPage(page_history.top());
  }
}
